Repository navigation
#140 PR4 List image channels and support NVR-attached cameras through ImageProxy - #151
Conversation
Add get_image_channels which lists the channel IDs a device accepts (ImageChannelInfo: id, enabled, input_port) from: /ISAPI/Image/channels (camera) /ISAPI/ContentMgmt/ImageProxy/channels (NVR) input_port is read from inputPort (NVR) or videoInputID (camera) An NVR serves the image settings of its attached cameras at /ISAPI/ContentMgmt/ImageProxy/channels/<id> (documented in Hikvision's NVR ISAPI guide) using the same ImageChannel document a camera serves. Add a proxy option to the image methods (get_image_settings, get_image_values, set_image_setting, set_image_linked_setting, put_image_settings) that addresses that path instead of /ISAPI/Image/channels/<id>. An NVR may list a channel whose camera it cannot proxy; reading it raises ISAPINotSupportedError.
mezz64
left a comment
There was a problem hiding this comment.
Thanks @baylanger. These changes look fine, but I'd like it to be tested on a real device before merging.
@ptarjan Any chance you can test this change? I believe you've tested on a Hik NVR in the past.
|
Tested on a real NVR: Hikvision DS-7608NI-EV2/8P, firmware V3.4.96 (build 181107), 8 attached cameras. Read-only (GET) calls only, at ad4c736.
Not tested: writes. |
|
I made a change to live_image_check.py , if you have time let me know if that works better. For your other comments, I'll try to figure out something. Thanx for the follow up. |
|
Thanks for testing on that "IPC" NVR. Maybe we'll need to test w/ a real NVR/DVR? Replying to the 2 most concening points:
That is what the NVR (IPC) sends. pyhik reports it unchanged as Callers should use channel IDs from If you'd rather have it raised as
I kept A caller that wants to fallback can check I can add a note about this to the README. Is this good enough? |
|
Thanks, that all sounds right to me.
|
Some recorders report deviceType IPC and answer the camera image endpoints with 503 serviceUnavailable or 400 badXmlContent. Explain that these raise a plain ISAPIError and that a caller can try proxy=True.
|
Fantastic. I just push a change to the README. |
|
Ran the updated No flags (auto-detect): fails This time the device-info read failed as well (the last run got
So the proxy path is solid. Auto-detect fails on this NVR when device info is unreadable. I'd suggest that a 503 |
|
Thanks for re-running it. Surely that was a bug in the script, I’ve changed it to what you suggested. The device type is now only a shortcut for NVR and DVR. Otherwise the script tries the camera endpoints and, if they fail w/ a device err such as 503 or 400, it tries proxy=True before giving up. A 401 or a connection error still counts as a camera. On your NVR a read-only run should now print "device type: unknown ... SAPIError"; then the camera image endpoints failed; trying the proxy endpoints, then proxy "endpoints: yes". Could you re-run it when you have a moment? |
|
Re-ran it read-only on the same NVR (DS-7608NI-EV2/8P, firmware V3.4.96) with the script at cd02ca2. Both runs pass now:
Thanks for the quick fix. The detection works on this recorder now. |
|
I just updated the README, replaced long paragraph 🙅 with a bullet list. Much easier to read. Is the last step before merging to write to a NVR? Who could do that ;) I'm going to create a new PR, not ready yet. It queries a camera or NVR, and save 3 documents (capabilities, channels, values) (per camera if it's a NVR) saving exactly what is returned from the device. End users can use this "dump" to troubleshot, open an issue, and can contribute their files in tests/fixtures/ ; A follow up PR will add the logic to the test_* to go over each files in the fixtures directory, thus possibly helping to identify any issues for future releases. If you like this idea or don't think this is need, let me know. |
|
@ptarjan when you have time, I have another request to hep me decide how to finalize the "dump" feature. Can you download and install dump.py and run It asks for:
It doesn't write anything to the camera, this is read-only. It will create a directory named from your "IPC IP address + date + time" and inside that directory it will have multiple files. I'm interested to know if the |
|
😆😆😆😆😆 ... I just realized you are the actual maintainers for the HA hikvision integration. I thought I'd have to deal with other people. |
|
Ha, yes, I'm a codeowner of the hikvision integration in HA (the HA maintainers own HA itself). Nice to work with you directly. Ran Your question: no, Other notes from the run:
Write test: I don't think it's possible on this NVR. The only proxied setting is the Dump/fixtures idea: 👍. Real device documents in |
|
I added to #154 writes to select and switches. As with numbers, if switch it will flip the current value (true to false or false to true) and flip it back. For select, it picks the first option in the device’s list that isn’t the current value, write once and then puts the original value. When you have time, give this a try : For the check the rejects fixtures files that has IP address, MAC, serials... it could run locally as a pre commit or a part of the githup workflow. I guess the pre-commit is best. You have a better choice? |
|
Ran the write test on the NVR with #154 at 7bef63b: So a write through ImageProxy works on this NVR, and the read-back and the restore both check out. Small side note: Fixture check: up to you and @mezz64. If it helps, a test in the GitHub workflow (or a pytest test over |
If you run ~ 2-3 times is the deviceInfo always unknown? If not, could always add 3 retries and give up after. |
Mostly, yes. Here is what I have from this NVR (DS-7608NI-EV2/8P, V3.4.96) over three days:
So 1 success out of 6 runs. Also, inside each failing run it was really tried 3 times back to back: (Edit: this turned out to be my test setup missing For what it's worth, I don't think retries would buy much here, but that's your and @mezz64's call. What #154 already does (treat a deviceInfo error like an unknown type and fall back to trying the proxy endpoints) is what made every one of those runs pass anyway. Even when deviceInfo does answer, it says I didn't record the exact status code. If it would help, I can capture it on the next run. |
|
Good idea caching the device_info and the script now prints the actual error text. |
|
Thanks, the error text found it. I need to correct what I said earlier: the NVR's deviceInfo isn't flaky. The problem was my test environment. I re-ran read-only on All checks passed (8 channels, settings, values). My venv was installed without the Two things worth taking from it:
|
|
I was slightly suspicious on the deviceInfo being flaky, it didn't seem right. Glad we have the real root cause.
I noticed I opt to make |
|
No objection from me as the hikvision integration's codeowner, but it's @mezz64's call as the maintainer. If it does become required, I'd expect nothing extra in the integration's manifest, since pip pulls it in with pyhik, and HA core already pins Moving to ElementTree later as a separate PR sounds reasonable to me, if @mezz64 wants to go that way. |
|
Nothing else from me on #151. I also read #153 again and have no concerns there, but of course both are up to @mezz64. On #154, module vs script: that's your and @mezz64's call. For what it's worth, a module would help with bug reports: anyone with pyhik installed (including inside an HA venv or container) could run something like
Looking forward to the HA PRs after the release. Ping me on them and I'll review as the integration's codeowner. The HA maintainers have the final say there, of course. |
mezz64
left a comment
There was a problem hiding this comment.
Thank you both for all the testing on this, i'll get it merged. @baylanger feel free to open up a new PR to add the xmltodict requirement, i'm ok with that.
Add get_image_channels which lists the channel IDs a device accepts (ImageChannelInfo: id, enabled, input_port) from:
/ISAPI/Image/channels (camera)
/ISAPI/ContentMgmt/ImageProxy/channels (NVR)
input_port is read from inputPort (NVR) or videoInputID (camera)
An NVR serves the image settings of its attached cameras at /ISAPI/ContentMgmt/ImageProxy/channels/ (documented in Hikvision's NVR ISAPI guide) using the same ImageChannel document a camera serves.
Add a proxy option to the image methods (get_image_settings, get_image_values, set_image_setting, set_image_linked_setting, put_image_settings) that addresses that path instead of /ISAPI/Image/channels/.
An NVR may list a channel whose camera it cannot proxy; reading it raises ISAPINotSupportedError.
Note: this is written based on Hikvision NVR ISAPI guide, someone will need to test this on a real NVR.
#140 PR4